using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Drawing;
using System.Text;
using System.Net;
using System.IO;
using System.Diagnostics;
using System.Text.RegularExpressions;
using Westwind.Tools.Http;
using System.Windows.Forms;

namespace Pix2Gallery2
{
    public class Gallery2Interface
    {
        static private Uri g2URL;
        static private CookieContainer reqLoginCookieContainer = new CookieContainer();
        static private HttpWebRequest g2WR;
        static private NameValueCollection nvColl = new NameValueCollection();
        private wwHttp oHttp;
        private string auth_token = "";
        private string fileName;

        private string gallery_protocol_version;
        private string gallery_file;
        private int gallery_version;

        private UploadProgressForm upProgForm = null;
        private Form parentForm = null;
        private Rectangle workingArea;
        private Rectangle rect;
        
        static private int uploadChunk = 16384;

        public Form ParentForm
        {
            get { return this.parentForm; }
            set { 
                this.parentForm = value;
                if (value == null)
                {
                    this.workingArea.Width = 0;
                    this.workingArea.Height = 0;
                    this.workingArea.X = 0;
                    this.workingArea.Y = 0;
                    this.rect.Width = 0;
                    this.rect.Height = 0;
                    this.rect.X = 0;
                    this.rect.Y = 0;
                }
                else
                {
                    this.workingArea = Screen.GetWorkingArea(value);
                    this.rect = value.Bounds;
                }
            }
        }

        private bool actionLogin = false;
        
        public Gallery2Interface(Uri G2URL)
        {
            g2URL = G2URL;

            //Assume Gallery2 first, and verify...
            this.gallery_protocol_version = @"2.5";
            this.gallery_file = @"/main.php";
            this.gallery_version = 2;
            //The no-op function only works in G2...
            if (!this.Gallery2NoOp())
            {
                this.gallery_protocol_version = @"2.1";
                this.gallery_file = @"/gallery_remote2.php";
                this.gallery_version = 1;
            }
        }

        //*** Gallery 1 versus Gallery 2 examples from galleryadd.pl

        //if ($gallery_version == 1) {
        //    $gallery_protocol_version = '2.1';
        //    $gallery_file = '/gallery_remote2.php';
        //} else {
        //    $gallery_protocol_version = '2.5';
        //    $gallery_file = '/main.php';
        //}
        

        //if ($gallery_version == 1) {
        //    $response = $ua->request (POST $gallery_fullurl,
        //        Content_Type	=> 'form-data',
        //        Content			=> [ 
        //            protocol_version	=> $gallery_protocol_version,
        //            cmd					=> "login",
        //            uname				=> $gallery_username,
        //            password			=> $gallery_password 
        //        ] );
        //} else {
        //    $response = $ua->request (POST $gallery_fullurl,
        //        Content_Type	=> 'form-data',
        //        Content			=> [
        //            'g2_controller'				=> 'remote:GalleryRemote',
        //            'g2_form[protocol_version]'	=> $gallery_protocol_version,
        //            'g2_form[cmd]'				=> "login",
        //            'g2_form[uname]'			=> $gallery_username,
        //            'g2_form[password]'			=> $gallery_password
        //        ] );
        //}

        public bool Gallery2NoOp()
        {
            if (this.oHttp == null)
                this.oHttp = new wwHttp();

            this.actionLogin = false;
            Trace.WriteLine(">> Gallery2Interface.Gallery2NoOp\r\n");

            wwHttp loHttp = this.oHttp;

            SetPostHeader(loHttp);
            loHttp.AddPostKey("g2_form[cmd]", "no-op");

            if (PostRequestData_wwHttp(loHttp) && nvColl["status"] == "0") return true;
            else return false;
        }

        public bool LoginToGallery2(string username, string password)
        {
            if (this.oHttp == null)
                this.oHttp = new wwHttp();

            this.actionLogin = true;
            Trace.WriteLine(">> Gallery2Interface.LoginToGallery2\r\n");

            wwHttp loHttp = this.oHttp;

            SetPostHeader(loHttp);
            if (this.gallery_version == 1)
            {
                loHttp.AddPostKey("cmd", "login");
                loHttp.AddPostKey("uname", username);
                loHttp.AddPostKey("password", password);
            }
            else
            {
                loHttp.AddPostKey("g2_form[cmd]", "login");
                loHttp.AddPostKey("g2_form[uname]", username);
                loHttp.AddPostKey("g2_form[password]", password);
            }

            if ( PostRequestData_wwHttp(loHttp) && nvColl["status"] == "0" ) return true;
            else return false;
        }

        public NameValueCollection GetAlbumList()
        {
            if (this.oHttp == null)
                this.oHttp = new wwHttp();

            this.actionLogin = false;
            Trace.WriteLine(">> Gallery2Interface.GetAlbumList\r\n");

           wwHttp loHttp = this.oHttp;
           
            SetPostHeader(loHttp);
            if (this.gallery_version == 1)
            {
                //loHttp.AddPostKey("cmd", "fetch-albums-prune");
                loHttp.AddPostKey("cmd", "fetch-albums");
                loHttp.AddPostKey("no_perms", "yes");
            }
            else
            {
                //loHttp.AddPostKey("g2_form[cmd]", "fetch-albums-prune");
                loHttp.AddPostKey("g2_form[cmd]", "fetch-albums");
                loHttp.AddPostKey("g2_form[no_perms]", "yes");
            }

            if (PostRequestData_wwHttp(loHttp) && nvColl.HasKeys())
            {
               Trace.WriteLine("In Get Album List " + nvColl.AllKeys[0].ToString());
                return nvColl;
            }
            else
            {
              Trace.WriteLine("It's Null");
                return null;
            }
        }


        public bool CreateNewAlbum(string newAlbumTitle, string newAlbumDesc, string albumParentName)
        {
            if (this.oHttp == null)
                this.oHttp = new wwHttp();

            this.actionLogin = false;
            Trace.WriteLine(">> Gallery2Interface.CreateNewAlbum: " + newAlbumTitle + "; " + newAlbumDesc + "; " + albumParentName + "\r\n");

            wwHttp loHttp = this.oHttp;

            SetPostHeader(loHttp);

            if (this.gallery_version == 1)
            {
                loHttp.AddPostKey("cmd", "new-album");
                loHttp.AddPostKey("set_albumName", albumParentName);
                loHttp.AddPostKey("newAlbumTitle", newAlbumTitle);
                if (newAlbumDesc != "")
                {
                    loHttp.AddPostKey("newAlbumDesc", newAlbumDesc);
                }
                //loHttp.AddPostKey("cmd", "new-album");
            }
            else
            {
                loHttp.AddPostKey("g2_form[cmd]", "new-album");
                loHttp.AddPostKey("g2_form[set_albumName]", albumParentName);
                loHttp.AddPostKey("g2_form[newAlbumTitle]", newAlbumTitle);
                if (newAlbumDesc != "")
                {
                    loHttp.AddPostKey("g2_form[newAlbumDesc]", newAlbumDesc);
                }
                //loHttp.AddPostKey("g2_form[cmd]", "new-album");
            }

            if (PostRequestData_wwHttp(loHttp) && nvColl["status"] == "0") return true;
            else return false;
        }

        //public bool UploadFileToAlbum(string albumName, string pictureCaption, string filePath)
        //{
        //    if (!File.Exists(filePath))
        //    {
        //        Trace.WriteLine(">>>> File " + filePath + " does not exist");
        //        return false;
        //    }

        //    if (this.oHttp == null)
        //        this.oHttp = new wwHttp();

        //    wwHttp loHttp = this.oHttp;

        //    this.actionLogin = false;
        //    Trace.WriteLine(">> Gallery2Interface.UploadFileToAlbum: " + albumName + "; " + pictureCaption + "; " + filePath + "\r\n");

        //    SetPostHeader(loHttp);

        //    loHttp.AddPostKey("g2_form[cmd]", "add-item");
        //    loHttp.AddPostKey("g2_form[set_albumName]", albumName);
        //    loHttp.AddPostImageFile("g2_userfile", filePath);
        //    loHttp.AddPostKey("g2_form[caption]", pictureCaption);
        //    loHttp.AddPostKey("g2_form[force_filename]", Path.GetFileName(filePath));
            
        //    if (PostRequestData_wwHttp(loHttp) && nvColl["status"] == "0") return true;
        //    else return false;
        //}

        public bool UploadFileToAlbum(string albumName, string pictureCaption, string filePath, string newFileName, string pictureSummary, string pictureDescription)
        {
            if (!File.Exists(filePath))
            {
                Trace.WriteLine(">>>> File " + filePath + " does not exist");
                return false;
            }

            if (this.oHttp == null)
                this.oHttp = new wwHttp();

            wwHttp loHttp = this.oHttp;

            this.actionLogin = false;
            Trace.WriteLine(">> Gallery2Interface.UploadFileToAlbum: " + albumName + "; " + pictureCaption + "; " + filePath + "\r\n");

            SetPostHeader(loHttp);

            this.fileName = filePath;

            if (this.gallery_version == 1)
            {
                loHttp.AddPostKey("cmd", "add-item");
                loHttp.AddPostKey("set_albumName", albumName);
                loHttp.AddPostImageFile("userfile", filePath);
                loHttp.AddPostKey("caption", pictureCaption);
                loHttp.AddPostKey("force_filename", newFileName);
                //>> 20070911 SM
                if ((pictureSummary != null) && (pictureSummary != ""))
                    loHttp.AddPostKey("extrafield.Summary", pictureSummary);
                if ((pictureDescription != null) && (pictureDescription != ""))
                    loHttp.AddPostKey("extrafield.Description", pictureDescription);
                //<< 20070911 SM
            }
            else
            {
                loHttp.AddPostKey("g2_form[cmd]", "add-item");
                loHttp.AddPostKey("g2_form[set_albumName]", albumName);
                loHttp.AddPostImageFile("g2_userfile", filePath);
                loHttp.AddPostKey("g2_form[caption]", pictureCaption);
                loHttp.AddPostKey("g2_form[force_filename]", newFileName);
                //>> 20070911 SM
                if ((pictureSummary != null) && (pictureSummary != ""))
                    loHttp.AddPostKey("g2_form[extrafield.Summary]", pictureSummary);
                if ((pictureDescription != null) && (pictureDescription != ""))
                    loHttp.AddPostKey("g2_form[extrafield.Description]", pictureDescription);
                //<< 20070911 SM
            }

            //if (PostRequestData_wwHttpEvents(loHttp, 16384) && nvColl["status"] == "0") return true;
            if (PostRequestData_wwHttp(loHttp) && nvColl["status"] == "0") return true;
            else return false;
        }
        //>> 20070913 SM
        //public bool UploadFileToAlbumEvents(string albumName, string pictureCaption, string filePath, string newFileName, bool useProgessForm)
        public bool UploadFileToAlbumEvents(string albumName, string pictureCaption, string filePath, string newFileName, string pictureSummary, string pictureDescription, bool useProgessForm)
        //<< 20070913 SM
        {
            if (!File.Exists(filePath))
            {
                Trace.WriteLine(">>>> File " + filePath + " does not exist");
                return false;
            }

            if (this.oHttp == null)
                this.oHttp = new wwHttp();

            wwHttp loHttp = this.oHttp;

            this.actionLogin = false;
            Trace.WriteLine(">> Gallery2Interface.UploadFileToAlbum: " + albumName + "; " + pictureCaption + "; " + filePath + "\r\n");

            SetPostHeader(loHttp);

            this.fileName = filePath;

            if (this.gallery_version == 1)
            {
                loHttp.AddPostKey("cmd", "add-item");
                loHttp.AddPostKey("set_albumName", albumName);
                loHttp.AddPostImageFile("userfile", filePath);
                loHttp.AddPostKey("caption", pictureCaption);
                loHttp.AddPostKey("force_filename", newFileName);
                //>> 20070913 SM
                if ((pictureSummary != null) && (pictureSummary != ""))
                    loHttp.AddPostKey("extrafield.Summary", pictureSummary);
                if ((pictureDescription != null) && (pictureDescription != ""))
                    loHttp.AddPostKey("extrafield.Description", pictureDescription);
                //<< 20070913 SM
            }
            else
            {
                loHttp.AddPostKey("g2_form[cmd]", "add-item");
                loHttp.AddPostKey("g2_form[set_albumName]", albumName);
                loHttp.AddPostImageFile("g2_userfile", filePath);
                loHttp.AddPostKey("g2_form[caption]", pictureCaption);
                loHttp.AddPostKey("g2_form[force_filename]", newFileName);
                //>> 20070913 SM
                if ((pictureSummary != null) && (pictureSummary != ""))
                    loHttp.AddPostKey("g2_form[extrafield.Summary]", pictureSummary);
                if ((pictureDescription != null) && (pictureDescription != ""))
                    loHttp.AddPostKey("g2_form[extrafield.Description]", pictureDescription);
                //<< 20070913 SM
            }

            if (PostRequestData_wwHttpEvents(loHttp, uploadChunk, useProgessForm) && nvColl["status"] == "0") return true;
            else return false;
        }

        public NameValueCollection GetPicturesForAlbum(string albumName)
        {
            //cmd=fetch-album-images
            //protocol_version=2.4
            //set_albumName=album-name
            //albums_too=yes/no [optional, since 2.13]
            //random=yes/no [optional, G2 since ***]
            //limit=number-of-images [optional, G2 since ***]

            if (this.oHttp == null)
                this.oHttp = new wwHttp();

            this.actionLogin = false;
            Trace.WriteLine(">> Gallery2Interface.GetPicturesForAlbum\r\n");

            wwHttp loHttp = this.oHttp;
            
            SetPostHeader(loHttp);

            if (this.gallery_version == 1)
            {
                loHttp.AddPostKey("cmd", "fetch-album-images");
                loHttp.AddPostKey("set_albumName", albumName);
            }
            else
            {
                loHttp.AddPostKey("g2_form[cmd]", "fetch-album-images");
                loHttp.AddPostKey("g2_form[set_albumName]", albumName);
            }
 
            if (PostRequestData_wwHttp(loHttp) && nvColl.HasKeys())
            {
                //Cache the collection here...
                return nvColl;
            }
            else 
            { 
                return null; 
            }
        }

        public string GetPicture(string albumName, string fileName, string fileUri)
        {
            string newPath = Path.GetTempPath() + @"Pix2Gallery2\Cache\" + albumName + @"\";
            Directory.CreateDirectory(newPath);  
            newPath = newPath + fileName;
            
            WebClient webClient = new WebClient();
            try
            {
                webClient.DownloadFile(fileUri, newPath);
            }
            catch (Exception e)
            {
                Trace.WriteLine(">> Gallery2Interface.GetPicture exception: " + e.Message);
                webClient.Dispose();
                return "";
            }

            webClient.Dispose();
            return newPath;
        }

        public void CleanupCachedFiles()
        {
            //For now, just delete the cached files, in the future, manage the size and delete the oldest
            string cachePath = Path.GetTempPath() + @"Pix2Gallery2\Cache\";

            // Create a new DirectoryInfo object.
            DirectoryInfo dir = new DirectoryInfo(cachePath);

            if (!dir.Exists)
            {
                Trace.WriteLine(">> Gallery2Interface.CleanupCachedFiles directory not found:" + cachePath);
                return;
            }

            // Call the GetFileSystemInfos method.
            FileSystemInfo[] infos = dir.GetFileSystemInfos(@"*.*");

            //Delete all the files first
            this.RecursiveDeleteFiles(infos, @"*.*");           

            //Then get rid of the directory
            try
            {
                Directory.Delete(cachePath, true);
            }
            catch (Exception e)
            {
                Trace.WriteLine(">> Exception in Gallery2Interface.CleanupCachedFiles: " + e.Message);
            }
        }

        private void RecursiveDeleteFiles(FileSystemInfo[] FSInfo, string SearchString)
        {
            // Check the parameters.
            if (FSInfo == null)
            {
                Trace.WriteLine(">> Gallery2Interface.RecursiveDeleteFiles FSInfo == null");
                return;
            }
            if (SearchString == null || SearchString.Length == 0)
            {
                Trace.WriteLine(">> Gallery2Interface.RecursiveDeleteFiles SearchString invalid");
                return;
            }

            // Iterate through each item.
            foreach (FileSystemInfo i in FSInfo)
            {
                // Check to see if this is a DirectoryInfo object.
                if (i is DirectoryInfo)
                {
                    // Cast the object to a DirectoryInfo object.
                    DirectoryInfo dInfo = (DirectoryInfo)i;

                    // Iterate through all sub-directories.
                    RecursiveDeleteFiles(dInfo.GetFileSystemInfos(SearchString), SearchString);
                }
                // Check to see if this is a FileInfo object.
                else if (i is FileInfo)
                {
                    //Delete all the files...
                    try
                    {
                        i.Delete();
                    }
                    catch (Exception e)
                    {
                        Trace.WriteLine(">> Gallery2Interface.RecursiveDeleteFiles Exception: " + e.Message);
                    }
                }
            }
        }
        
        private void PostRequestData()
        {
            string postData = GetPostData();

            Trace.WriteLine(">> Gallery2Interface.PostRequestData\r\n");

            if(this.actionLogin) Debug.WriteLine(">> postData = " + postData);
            else Trace.WriteLine(">> postData = " + postData);

            byte[] requestData = Encoding.UTF8.GetBytes(postData);

            Uri reqUri = new Uri(g2URL.ToString() + this.gallery_file);
            g2WR = (HttpWebRequest)HttpWebRequest.Create(reqUri);
            g2WR.Method = "POST";

            g2WR.ContentType = "application/x-www-form-urlencoded";
            g2WR.ContentLength = requestData.Length;
            g2WR.AllowWriteStreamBuffering = true;
            g2WR.AllowAutoRedirect = true;
            g2WR.Timeout = 30000;

            //Enable cookies...
            g2WR.CookieContainer = reqLoginCookieContainer;

            HttpWebResponse response = null;

            try
            {
                Stream newStream = g2WR.GetRequestStream();
                newStream.Write(requestData, 0, requestData.Length);
                newStream.Close();

                response = (HttpWebResponse)g2WR.GetResponse();
            }
            catch (WebException webE)
            {
                Trace.WriteLine(">> WebException on WebRequest");
                Trace.WriteLine(">> Status is " + webE.Status);
            }
            finally
            {
                if (g2WR != null)
                {
                    Trace.WriteLine(">> Content Uri is " + g2WR.RequestUri);
                    Trace.WriteLine(">> Connection is " + g2WR.Connection);
                }

                if (response != null)
                {
                    Trace.WriteLine(">> Content length is " + response.ContentLength);
                    Trace.WriteLine(">> Content type is " + response.ContentType);
                    Trace.WriteLine(">> Content encoding is " + response.ContentEncoding);
                    Trace.WriteLine(">> Last modified is " + response.LastModified);
                    Trace.WriteLine(">> Server is " + response.Server);
                    Trace.WriteLine(">> Character set is " + response.CharacterSet);
                    Trace.WriteLine(">> Status code is " + response.StatusCode);
                    Trace.WriteLine(">> Status description is " + response.StatusDescription);
                    Trace.WriteLine(">> Response headers are\n" + response.Headers.ToString());

                    Stream responseStream = response.GetResponseStream();

                    int numProps = SetPropertyPairs(responseStream);
                    Trace.WriteLine(">> Number properties recieved is " + numProps);

                    response.Close();
                }
            }
        }

        private void PostRequestData_wwHttp()
        {
            string postData = GetPostData();

            Trace.WriteLine(">> Gallery2Interface.PostRequestData_wwHttp\r\n");

            if (this.actionLogin) Debug.WriteLine(">> postData = " + postData);
            else Trace.WriteLine(">> postData = " + postData);
            
  			if ( this.oHttp == null)
				this.oHttp = new wwHttp();

			wwHttp loHttp = this.oHttp;

            loHttp.PostMode = 1;
			loHttp.HandleCookies = true;
            loHttp.Timeout = 30;
            if (postData.Length > 0)
				loHttp.AddPostKey(postData);

            StreamReader responseStreamReader = loHttp.GetUrlStream(g2URL.ToString() + this.gallery_file);

            if(loHttp.WebResponse != null){
                Trace.WriteLine(">> RequestHeaders:");
                Trace.Write(loHttp.WebRequest.Headers.ToString());
                Trace.WriteLine(">> ResponseHeaders:");
                Trace.Write(loHttp.WebResponse.Headers.ToString());
                
                int numProps = SetPropertyPairs(responseStreamReader);
                Trace.WriteLine(">> Number properties received 1 is " + numProps);
            }
        }

        private bool PostRequestData_wwHttp(wwHttp loHttp)
        {
            Trace.WriteLine(">> Gallery2Interface.PostRequestData_wwHttp(wwHttp loHttp)\r\n");

            StreamReader responseStreamReader = loHttp.GetUrlStream(g2URL.ToString() + this.gallery_file);

            if (loHttp.Error)
            {
                Trace.WriteLine("\r\n<ERROR>\r\n>> wwHttp Error: " + loHttp.ErrorMsg.ToString());
                Trace.WriteLine(">> RequestHeaders:");
                Trace.Write(loHttp.WebRequest.Headers.ToString());
                if (loHttp.WebResponse != null)
                {
                    Trace.WriteLine(">> ResponseHeaders:");
                    Trace.Write(loHttp.WebResponse.Headers.ToString());
                }
                Trace.WriteLine("</ERROR>\r\n");
                return false;
            }

            if (loHttp.WebResponse != null)
            {
                Trace.WriteLine(">> RequestHeaders:");
                Trace.Write(loHttp.WebRequest.Headers.ToString());
                Trace.WriteLine(">> ResponseHeaders:");
                Trace.Write(loHttp.WebResponse.Headers.ToString());

                int numProps = SetPropertyPairs(responseStreamReader);
                Trace.WriteLine("\r\n>>>> Number properties received 2 is " + numProps + "\r\n");
               // 20081017  wcf If status = 0 (success) not received 
                if (numProps == -1)
                return false;
                 }

            return true;
        }

        public void OnWriteData(object sender, wwHttp.OnWriteDataEventArgs e)
        {
            Trace.WriteLine("\r\n>>>>>>> CurrentByteCount = " + e.CurrentByteCount);
            Trace.WriteLine(">>>>>>> TotalBytes       = " + e.TotalBytes);
            Trace.WriteLine(">>>>>>> NumberOfWrites   = " + e.NumberOfWrites);

            if (this.upProgForm != null)
            {
                this.upProgForm.progressBarUpload.Maximum = (int)e.TotalBytes;
                this.upProgForm.progressBarUpload.Value = (int)e.CurrentByteCount;
                this.upProgForm.labelProgressText.Text = "Uploaded " + e.CurrentByteCount.ToString() + " bytes of " + e.TotalBytes.ToString() + " bytes";
                //this.upProgForm.Visible = true;
                this.upProgForm.Refresh();
            }
        }

        ///<summary>The Form '<paramref name="form"/>' will be displayed centered in the '<paramref name="containerForm"/>'</summary>
        protected void CenterFormToParent(Form form)
        {
            if (this.rect.IsEmpty) return;
            if (this.workingArea.IsEmpty) return;

            Point point = new Point(); 
            Size formSize = form.Size;  
            point.X = ((rect.Left + rect.Right) - formSize.Width) / 2;  
            if (point.X < workingArea.X) point.X = workingArea.X;  
            else if ((point.X+formSize.Width) > (workingArea.X+workingArea.Width))      
                point.X = (workingArea.X + workingArea.Width) - formSize.Width;  
            point.Y = ((rect.Top + rect.Bottom) - formSize.Height) / 2;  
            if (point.Y < workingArea.Y) point.Y = workingArea.Y;  
            else if ((point.Y+formSize.Height) > (workingArea.Y+workingArea.Height))  
                point.Y = (workingArea.Y + workingArea.Height) - formSize.Height;  
            form.Location = point;
        } 
        
        private bool PostRequestData_wwHttpEvents (wwHttp loHttp, int bufferSize, bool useProgressForm)
        {
            Trace.WriteLine(">> Gallery2Interface.PostRequestData_wwHttpEvents(wwHttp loHttp, int bufferSize)\r\n");

            //Hook up the event handler
            wwHttp.OnWriteDataHandler writeHandler = new wwHttp.OnWriteDataHandler(this.OnWriteData);
            loHttp.OnWriteData += writeHandler;

            if (useProgressForm)
            {
                this.upProgForm = new UploadProgressForm();
                this.upProgForm.labelFilename.Text = "Uploading file " + this.fileName;
                this.upProgForm.progressBarUpload.Minimum = 0;
                this.upProgForm.progressBarUpload.Value = 0;
                //this.upProgForm.Visible = false;
                //if (this.parentForm != null)
                //{
                //    this.upProgForm.Location = this.parentForm.Location;
                //}
                this.upProgForm.Show();
                this.CenterFormToParent(this.upProgForm);
                this.upProgForm.Refresh();
            }

            //Write the stream...
            StreamReader responseStreamReader = loHttp.GetUrlStreamEvents(g2URL.ToString() + this.gallery_file, bufferSize);

            //Cancel the event handler...
            loHttp.OnWriteData -= writeHandler;

            if (this.upProgForm != null)
            {
                this.upProgForm.Close();
                this.upProgForm = null;
            }

            if (loHttp.Error)
            {
                Trace.WriteLine("\r\n<ERROR>\r\n>> wwHttp Error: " + loHttp.ErrorMsg.ToString());
                Trace.WriteLine(">> RequestHeaders:");
                Trace.Write(loHttp.WebRequest.Headers.ToString());
                if (loHttp.WebResponse != null)
                {
                    Trace.WriteLine(">> ResponseHeaders:");
                    Trace.Write(loHttp.WebResponse.Headers.ToString());
                }
                Trace.WriteLine("</ERROR>\r\n");
                return false;
            }

            if (loHttp.WebResponse != null)
            {
                Trace.WriteLine(">> RequestHeaders:");
                Trace.Write(loHttp.WebRequest.Headers.ToString());
                Trace.WriteLine(">> ResponseHeaders:");
                Trace.Write(loHttp.WebResponse.Headers.ToString());

                int numProps = SetPropertyPairs(responseStreamReader);
                Trace.WriteLine("\r\n>>>> Number properties received 3 is " + numProps + "\r\n");
            }

            return true;
        }

        private void PostMultipartRequestData()
        {
            Trace.WriteLine(">> Gallery2Interface.PostMultipartRequestData\r\n");
            
            string postData = GetPostData();

            if (this.actionLogin) Debug.WriteLine(">> postData = " + postData);
            else Trace.WriteLine(">> postData = " + postData);

            byte[] requestData = Encoding.UTF8.GetBytes(postData);
            
            //Uri reqUri = new Uri(g2URL.ToString() + "/main.php");
            Uri reqUri = new Uri(g2URL.ToString() + this.gallery_file);
            g2WR = (HttpWebRequest)HttpWebRequest.Create(reqUri);
            g2WR.Method = "POST";

            g2WR.ContentType = "multiform/form-data";
            g2WR.ContentLength = requestData.Length;
            g2WR.AllowWriteStreamBuffering = true;
            g2WR.AllowAutoRedirect = true;
            g2WR.Timeout = 60000;

            //Enable cookies...
            g2WR.CookieContainer = reqLoginCookieContainer;

            HttpWebResponse response = null;

            try
            {
                Stream newStream = g2WR.GetRequestStream();
                newStream.Write(requestData, 0, requestData.Length);
                newStream.Close();

                response = (HttpWebResponse)g2WR.GetResponse();
            }
            catch (WebException webE)
            {
                Trace.WriteLine(">> WebException on WebRequest");
                Trace.WriteLine(">> Status is " + webE.Status);
            }
            finally
            {
                if (g2WR != null)
                {
                    Trace.WriteLine(">> Content Uri is " + g2WR.RequestUri);
                    Trace.WriteLine(">> Connection is " + g2WR.Connection);
                }

                if (response != null)
                {
                    Trace.WriteLine(">> Content length is " + response.ContentLength);
                    Trace.WriteLine(">> Content type is " + response.ContentType);
                    Trace.WriteLine(">> Content encoding is " + response.ContentEncoding);
                    Trace.WriteLine(">> Last modified is " + response.LastModified);
                    Trace.WriteLine(">> Server is " + response.Server);
                    Trace.WriteLine(">> Character set is " + response.CharacterSet);
                    Trace.WriteLine(">> Status code is " + response.StatusCode);
                    Trace.WriteLine(">> Status description is " + response.StatusDescription);
                    Trace.WriteLine(">> Response headers are\n" + response.Headers.ToString());

                    Stream responseStream = response.GetResponseStream();

                    int numProps = SetPropertyPairs(responseStream);
                    Trace.WriteLine(">> Number properties recieved is " + numProps);

                    response.Close();
                }
            }
        }

        private int DisplayPageContent(Stream ReceiveStream)
        {

            Trace.WriteLine(">> Gallery2Interface.DisplayPageContent\r\n");
            
            // Create an ASCII encoding object.
            Encoding ASCII = Encoding.ASCII;

            // Define the byte array to temporarily hold the current read bytes. 
            Byte[] read = new Byte[512];

            Debug.WriteLine(">> Page Content...");

            // Read the page content and display it on the console.
            // Read the first 512 bytes.            
            int totalBytesRead = 0;
            int bytesRead = ReceiveStream.Read(read, 0, 512);
            string sRead;

            while (bytesRead > 0)
            {
                totalBytesRead += bytesRead;
                sRead = ASCII.GetString(read, 0, bytesRead);
                Debug.WriteLine(">>>>> Bytes read is " + totalBytesRead);
                Debug.WriteLine(sRead);
                bytesRead = ReceiveStream.Read(read, 0, 512);
            }

            return totalBytesRead;
        }      

        private int SetPropertyPairs(Stream receiveStream)
        {
            if (receiveStream == null) return -1;
            
            nvColl.Clear();

            Encoding encode = System.Text.Encoding.GetEncoding("utf-8");
            // Pipes the stream to a higher level stream reader with the required encoding format. 
            StreamReader readStream = new StreamReader( receiveStream, encode );

            Regex firstLineRegex = new Regex("^[#][^=]");
            Regex propPairRegex = new Regex("(?<name>[^=]+)=(?<value>.+)");

            while (readStream.Peek() >= 0) 
            {
                string readLine = readStream.ReadLine();
                Trace.WriteLine("<> " + readLine);

                Match mFirstLine = firstLineRegex.Match(readLine);
                Match mPropPair = propPairRegex.Match(readLine);

                if (mFirstLine.Success)
                {
                    nvColl.Add("header", readLine);
                }
                else if (mPropPair.Success)
                {
                    nvColl.Add(mPropPair.Groups["name"].Value.ToString(), mPropPair.Groups["value"].Value.ToString());
                }
            }

            if (nvColl["auth_token"] != null) this.auth_token = nvColl["auth_token"];
            else this.auth_token = "";

            return (nvColl.Count);
        }

        private int SetPropertyPairs(StreamReader receiveStreamReader)
        {
            Trace.WriteLine(">> Gallery2Interface.SetPropertyPairs(StreamReader receiveStreamReader)\r\n");
            
            if (receiveStreamReader == null) return -1;
           
            nvColl.Clear();

            Regex firstLineRegex = new Regex(@"^[#][^=]");
            Regex propPairRegex = new Regex(@"(?<name>[^=]+)=(?<value>.+)");

            while (receiveStreamReader.Peek() >= 0)
            {
                string readLine = receiveStreamReader.ReadLine();
                Trace.WriteLine("<> " + readLine);

                Match mFirstLine = firstLineRegex.Match(readLine);
                Match mPropPair = propPairRegex.Match(readLine);

                if (mFirstLine.Success)
                {
                    nvColl.Add("header", readLine);
                }
                else if (mPropPair.Success)
                {
                    string value = Regex.Unescape(mPropPair.Groups["value"].Value.ToString());
                    nvColl.Add(mPropPair.Groups["name"].Value.ToString(), value);
                }
            }

            if (nvColl["auth_token"] != null) this.auth_token = nvColl["auth_token"];
            else this.auth_token = "";
            if (nvColl["status"] != null)
            {
                return (nvColl.Count);
            }
            else
            {
                return -1;
            }
            //return (nvColl.Count);
        }
        
        private void SetPostHeader()
        {
            nvColl.Clear();

            if (this.gallery_version == 1)
            {
                nvColl.Add("protocol_version", this.gallery_protocol_version);
            }
            else
            {
                nvColl.Add("g2_form[protocol_version]", this.gallery_protocol_version);
                nvColl.Add("g2_controller", "remote.GalleryRemote");
                if (this.auth_token != "")
                {
                    nvColl.Add("g2_authToken", this.auth_token);
                }
            }
         }

        private void SetPostHeader(wwHttp loHttp)
        {
            loHttp.PostMode = 2;
            loHttp.HandleCookies = true;
            loHttp.Timeout = 100;

            if (this.gallery_version == 1)
            {
                loHttp.AddPostKey("protocol_version", this.gallery_protocol_version);
            }
            else
            {
                loHttp.AddPostKey("g2_form[protocol_version]", this.gallery_protocol_version);
                loHttp.AddPostKey("g2_controller", "remote.GalleryRemote");
                if (this.auth_token != "")
                {
                    loHttp.AddPostKey("g2_authToken", this.auth_token);
                }
            }
        }
        
        private string GetPostData()
        {
            int i;
            string postData = "";

            for (i = 0; i < nvColl.Count - 1; i++ )
            {
                postData += nvColl.GetKey(i) + "=" + nvColl.Get(i) + "&";
            }

            i = nvColl.Count - 1;
            postData += nvColl.GetKey(i) + "=" + nvColl.Get(i);

            return postData;
        }
    }
}
